import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { OperationLog } from '../modules/operation-log/entities/operation-log.entity';
import { User } from '../modules/user/entities/user.entity';
import { LogSanitizer } from '../utils/log-sanitizer.util';

@Injectable()
export class OperationLogInterceptor implements NestInterceptor {
  constructor(
    @InjectRepository(OperationLog)
    private readonly operationLogRepository: Repository<OperationLog>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  private getClientIp(request: any): string {
    let clientIp = request.ip;
    const forwardedFor = request.headers['x-forwarded-for'];
    if (forwardedFor) {
      clientIp = forwardedFor.split(',')[0].trim();
    }
    if (clientIp.startsWith('::ffff:')) {
      clientIp = clientIp.substring(7);
    }
    return clientIp;
  }

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const startTime = Date.now();
    const response = context.switchToHttp().getResponse();

    return next.handle().pipe(
      tap(async () => {
        try {
          const duration = Date.now() - startTime;
          const clientIp = this.getClientIp(request);

          // 获取用户详细信息
          let username = null;
          let phone = null;
          if (request.user?.id) {
            const user = await this.userRepository.findOne({
              where: { id: request.user.id },
              select: ['username', 'phone']
            });
            if (user) {
              username = user.username || user.phone; // 如果没有用户名就使用手机号
              phone = user.phone;
            }
          }

          const logEntry = this.operationLogRepository.create({
            userId: request.user?.id,
            username,
            phone,
            method: request.method,
            path: request.url,
            params: LogSanitizer.truncateData(LogSanitizer.sanitizeRequest(request.params)),
            body: LogSanitizer.truncateData(LogSanitizer.sanitizeRequest(request.body)),
            ip: clientIp,
            userAgent: request.headers['user-agent'],
            status: response.statusCode,
            duration,
            operationType: this.getOperationType(request.method, request.url),
            createdAt: new Date() // 手动设置当前时间，包含毫秒
          });

          await this.operationLogRepository.save(logEntry);
        } catch (error) {
          console.error('Failed to save operation log:', error);
        }
      }),
    );
  }

  private getOperationType(method: string, url: string): string {
    if (url.includes('/auth')) return 'AUTH';
    if (url.includes('/user')) return 'USER';
    if (method === 'GET') return 'QUERY';
    if (method === 'POST') return 'CREATE';
    if (method === 'PUT') return 'UPDATE';
    if (method === 'DELETE') return 'DELETE';
    return 'OTHER';
  }
}










